package com.sat.client.fragment

import android.graphics.SurfaceTexture
import android.media.MediaCodec
import android.media.MediaCodecInfo
import android.media.MediaFormat
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.Surface
import android.view.TextureView
import java.nio.ByteBuffer

class VideoPlayer(
    private val textureView: TextureView
) : TextureView.SurfaceTextureListener {

    private var mediaCodec: MediaCodec? = null
    private var surface: Surface? = null
    private val handler = Handler(Looper.getMainLooper())

    init {
        textureView.surfaceTextureListener = this
    }

    override fun onSurfaceTextureAvailable(
        surfaceTexture: SurfaceTexture,
        width: Int,
        height: Int
    ) {
        surface = Surface(surfaceTexture)
        initializeCodec()
    }

    override fun onSurfaceTextureSizeChanged(
        surfaceTexture: SurfaceTexture,
        width: Int,
        height: Int
    ) {
    }

    override fun onSurfaceTextureUpdated(surfaceTexture: SurfaceTexture) {}

    override fun onSurfaceTextureDestroyed(surfaceTexture: SurfaceTexture): Boolean {
        surface?.release()
        mediaCodec?.release()
        return true
    }

    private fun initializeCodec() {
        val codecName = "video/hevc" // H.265
        val codecFormat = MediaFormat.createVideoFormat(
            codecName, 1280, 720
        ) // Adjust size as needed
        codecFormat.setInteger(
            MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface
        )
        codecFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30)
        codecFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1)

        mediaCodec = MediaCodec.createDecoderByType(codecName)
        mediaCodec?.configure(codecFormat, surface, null, 0)
        mediaCodec?.start()

        // You can now feed data to the decoder
    }

    fun feedData(data: ByteArray) {
        handler.post {
            val inputBufferIndex = mediaCodec?.dequeueInputBuffer(10000) ?: return@post
            val inputBuffer = mediaCodec?.getInputBuffer(inputBufferIndex) ?: return@post
            inputBuffer.clear()
            inputBuffer.put(data)
            mediaCodec?.queueInputBuffer(
                inputBufferIndex,
                0,
                data.size,
                System.nanoTime() / 1000,
                0
            )
            processOutput()
        }
    }

    private fun processOutput() {
        val bufferInfo = MediaCodec.BufferInfo()
        var outputBufferIndex = mediaCodec?.dequeueOutputBuffer(bufferInfo, 10000) ?: return
        while (outputBufferIndex >= 0) {
            mediaCodec?.releaseOutputBuffer(outputBufferIndex, true)
            outputBufferIndex = mediaCodec?.dequeueOutputBuffer(bufferInfo, 0) ?: -1
        }
    }
}
